/*
 * 文件名：MyInvocationSecurityMetadataSourceService.java
 * 版权：Copyright by www.wootide.com
 * 描述：
 * 修改人：ozm
 * 修改时间：2013-1-25
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */
package com.wootide.ets.sys.security.datasource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
import org.springframework.stereotype.Service;

import com.wootide.ets.sys.menu.dao.MenuInfoDao;

/*//1 加载资源与权限的对应关系  
public class MySecurityMetadataSource implements
        FilterInvocationSecurityMetadataSource
{
    
//    private UrlMatcher urlMatcher = new AntUrlPathMatcher();;
//    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
//
//    public void MyInvocationSecurityMetadataSource() {
//        loadResourceDefine();
//    }
//
//    private void loadResourceDefine() {
//        resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
//        Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
//        ConfigAttribute ca = new SecurityConfig("ROLE_ADMIN");
//        atts.add(ca);
//        resourceMap.put("/index.jsp", atts);
//        resourceMap.put("/i.jsp", atts);
//    }
//
//    // According to a URL, Find out permission configuration of this URL.
//    public Collection<ConfigAttribute> getAttributes(Object object)
//            throws IllegalArgumentException {
//        // guess object is a URL.
//        String url = ((FilterInvocation)object).getRequestUrl();
//        Iterator<String> ite = resourceMap.keySet().iterator();
//        while (ite.hasNext()) {
//            String resURL = ite.next();
//            if (urlMatcher.pathMatchesUrl(resURL, url)) {
//                return resourceMap.get(resURL);
//            }
//        }
//        return null;
//    }
//
    public boolean supports(Class<?> clazz) {
        return true;
    }
    
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

/**
 * 加载资源与权限的对应关系
 * 〈功能详细描述〉
 * @author wuliquan
 * @version 2013-6-25
 * @see MySecurityMetadataSource
 * @since
 */

/** *//**
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。 此类在初始化时，应该取到所有资源及其对应角色的定义。
 * 
 */
@Service
public class MySecurityMetadataSource implements
        FilterInvocationSecurityMetadataSource
{
    
    private MenuInfoDao menuInfoDao;
    
    private UrlMatcher urlMatcher = new AntUrlPathMatcher();
    
    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
    
    //由spring调用
    public MySecurityMetadataSource(MenuInfoDao menuInfoDao)
    {
        this.menuInfoDao = menuInfoDao;
        loadResourceDefine();
    }
    
    public MySecurityMetadataSource()
    {
        
    }
    
    public Collection<ConfigAttribute> getAllConfigAttributes()
    {
        return null;
    }
    
    public boolean supports(Class<?> clazz)
    {
        return true;
    }
    
    /**
     * 加载所有资源与权限的关系
     * Description: <br>
     * Implement: <br>
     * @see
     * @return void
     * @author wuliquan
     */
    /*private void loadResourceDefine()
    {
        if (resourceMap == null)
        {
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
            List<MenuInfo> menuInfos = menuInfoDao.findAllMenus();
            for (MenuInfo menuInfo : menuInfos)
            {
                Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
                //以权限名封装为Spring的security Object
                ConfigAttribute configAttribute = new SecurityConfig(
                        menuInfo.getMenuName());
                configAttributes.add(configAttribute);
                
                ConfigAttribute configAttribute1 = new SecurityConfig(
                        menuInfo.getMenuName());
                Collection<ConfigAttribute> configAttributes1 = new ArrayList<ConfigAttribute>();
                resourceMap.put("/index.jsp", configAttributes1);
                
                
                //resourceMap.put(menuInfo.getMenuUrl(), configAttributes);
            }
        }
        
        Set<Entry<String, Collection<ConfigAttribute>>> resourceSet = resourceMap.entrySet();
        Iterator<Entry<String, Collection<ConfigAttribute>>> iterator = resourceSet.iterator();
        
    }*/
    
    
    private void loadResourceDefine() {
        ApplicationContext context = new ClassPathXmlApplicationContext(
          "classpath:applicationContext.xml");

        SessionFactory sessionFactory = (SessionFactory) context
          .getBean("sessionFactory");

        Session session = sessionFactory.openSession();

        String username = "";
        
        String sql = "";

        // 在Web服务器启动时，提取系统中的所有权限。
        sql = "select AuthorityName from authoritiesinfo";

        List<String> authorities = session.createSQLQuery(sql).list();

        /**//*
         * 应当是菜单为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
         * 
         */
        resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

        for (String auth : authorities) {
            
         ConfigAttribute ca = new SecurityConfig(auth);
         
        /* List<String> query1 = session.createSQLQuery(
             "select b.MenuUrl from authoritymenu a, menuinfo b,authoritiesinfo c where a.MenuId = b.MenuId "
               + "and a.AuthorityId = c.AuthorityId and c.AuthorityName='"
               + auth + "'").list();*/
         String hqlStr = "select b.menuUrl from AuthoritiesMenu a, MenuInfo b,AuthoritiesInfo c where a.menuInfo.menuId = b.menuId" +
        " and a.authoritiesInfo.authorityId = c.authorityId and c.authorityName= 'ROLE_ADMIN'";
         
         List<String> query1 = session.createQuery(hqlStr).list();
         
         
         /*List<String> query1 = session.createSQLQuery("select b.MenuUrl from authoritymenu a, menuinfo b,authoritiesinfo c where a.MenuId = b.MenuId" +
        " and a.AuthorityId = c.AuthorityId and c.AuthorityName= 'ROLE_ADMIN'").list();*/
         

         for (String res : query1) {
          String url = res;
          
          /**
           * 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。
           */
          if (resourceMap.containsKey(url)) {

           Collection<ConfigAttribute> value = resourceMap.get(url);
           value.add(ca);
           resourceMap.put(url, value);
          } else {
           Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
           atts.add(ca);
           resourceMap.put(url, atts);
          }

         }

        }

       }
    
 // 根据URL，找到相关的权限配置。
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object)
      throws IllegalArgumentException {

     // object 是一个URL，被用户请求的url。
     String url = ((FilterInvocation) object).getRequestUrl();
     
           int firstQuestionMarkIndex = url.indexOf("?");

           if (firstQuestionMarkIndex != -1) {
               url = url.substring(0, firstQuestionMarkIndex);
           }

           if (resourceMap == null)
           {
               loadResourceDefine();
           }
     Iterator<String> ite = resourceMap.keySet().iterator();

     while (ite.hasNext()) {
      String resURL = ite.next();
      
      if (urlMatcher.pathMatchesUrl(url, resURL)) {

       return resourceMap.get(resURL);
      }
     }

     return null;
    }
    
    
    /*//返回所请求资源所需要的权限
    public Collection<ConfigAttribute> getAttributes(Object object)
            throws IllegalArgumentException
    {
        
        String requestUrl = ((FilterInvocation)object).getRequestUrl();
        System.out.println("MySecurityMetadataSource-----147:equestUrl is " + requestUrl);
        if (resourceMap == null)
        {
            loadResourceDefine();
        }
        return resourceMap.get(requestUrl);
    }*/

    public MenuInfoDao getMenuInfoDao()
    {
        return menuInfoDao;
    }

    public void setMenuInfoDao(MenuInfoDao menuInfoDao)
    {
        this.menuInfoDao = menuInfoDao;
    }
}
